package com.fingard.dsp.bank.directbank.bocom13;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.bocom13.util.Mac;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;

public class BOCOM13Base extends DirectBase implements ITcpClient {
    private static TransIDHelper idHelper = new TransIDHelper(1, 999);
    private  String tmpmacKey="macKey";
    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    protected String getCharset() {
        return getBankConfig().getCharset("UTF-8");
    }

    /**
     * 拆分byte数组
     *
     * @param bytes  要拆分的数组
     * @param copies 要按几个组成一份
     * @return
     */
    static byte[][] split_bytes(byte[] bytes, int copies) {
        double split_length = Double.parseDouble(copies + "");
        int array_length = (int) Math.ceil(bytes.length / split_length);
        byte[][] result = new byte[array_length][];
        int from, to;
        for (int i = 0; i < array_length; i++) {
            from = (int) (i * split_length);
            to = (int) (from + split_length);
            if (to > bytes.length)
                to = bytes.length;
            result[i] = Arrays.copyOfRange(bytes, from, to);
        }
        return result;
    }

    /**
     * 获取批次序号
     *
     * @param tmpReqDir 当前目录
     * @param length    固定长度位数
     * @return 实际批次序号
     */
    public static String getBatSeqNo(String tmpReqDir, int length) {
        int batSeqNo = 0;
        File tmpFileDir = new File(tmpReqDir);
        if (tmpFileDir.exists()) {
            File[] tmpFileList = tmpFileDir.listFiles();
            if (tmpFileList != null) {
                int i = 0;
                for (File tmpFile : tmpFileList) {
                    if (tmpFile.getName().endsWith(".gz")) {
                        i++;
                    }
                }
                batSeqNo = i + 1;
            } else {
                batSeqNo = 1;
            }
        } else {
            batSeqNo++;
        }
        String strFmt="%0" + length + "d";
        return String.format(strFmt, batSeqNo);
    }

    public String getNotifyDirectory() {
        return FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "NotifyData" + File.separator + reqHeader.bankCode;
    }

    public String createNotifyDirectory() {
        String dir = FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "NotifyData" + File.separator + reqHeader.bankCode;
        File mdDir = new File(dir);
        if (!mdDir.exists()) {
            mdDir.mkdirs();
        }
        return dir;
    }

    public static int getGZipFileLen(String fileName) throws IOException {
        FileInputStream fis=null;
        int zipFileLen=0;
        try {
             fis = new FileInputStream(new File(fileName));
            zipFileLen=fis.available();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fis!=null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        return zipFileLen;
    }

    /**
     * 拼接联机交易通用报文头
     *
     * @param xmlWriter
     * @param tmpBankHeader
     * @throws Exception
     */
    protected void writeCommonHeader(XmlTextWriter xmlWriter, BOCOM13Header tmpBankHeader) {
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("Req");
        xmlWriter.writeStartElement("Head");
        xmlWriter.writeElementString("TrCode", tmpBankHeader.transCode);/* 交易码:参见《交通银行资金清算平台数据字典》2.1交易码 */
        xmlWriter.writeStartElement("Sender");/* 交易请求方 */
        xmlWriter.writeElementString("OrgType", "I");/* 机构类型 */
        xmlWriter.writeElementString("OrgId", tmpBankHeader.corpNo);/* 机构ID */
        xmlWriter.writeElementString("BrchId", "");/* 交易区域(保险分公司编码) */
        xmlWriter.writeElementString("SubBrchId", "");/* 交易机构 */
        xmlWriter.writeElementString("TermId", "");/* 交易终端号 */
        xmlWriter.writeElementString("TrOper", "");/* 交易柜员号(保险方柜员代码) */
        xmlWriter.writeElementString("TrOperName", "");/* 交易柜员名称(保险方柜员名称) */
        xmlWriter.writeElementString("ChanNo", "93");/* 交易渠道(固定填写"93") */
        xmlWriter.writeElementString("OriBusDate", "");/* 原业务日期 */
        xmlWriter.writeElementString("OriSeqNo", tmpBankHeader.reqSeqID);/* 原交易流水号 */
        xmlWriter.writeElementString("BusDate", Format.Date8Format.format(new Date()));/* 业务日期 */
        xmlWriter.writeElementString("SeqNo", tmpBankHeader.reqSeqID);/* 交易流水号 */
        xmlWriter.writeElementString("TrDate", Format.Date8Format.format(new Date()));/* 交易日期 */
        xmlWriter.writeElementString("TrTime", Format.Time6Format.format(new Date()));/* 交易时间 */
        xmlWriter.writeEndElement();
        xmlWriter.writeStartElement("Recver");/* 交易应答方 */
        xmlWriter.writeElementString("OrgType", "B");/* 机构类型 */
        xmlWriter.writeElementString("OrgId", "3012900");/* 机构ID(3012900:交通银行) */
        xmlWriter.writeElementString("BrchId", "");/* 交易区域(银行分行代码) */
        xmlWriter.writeElementString("SubBrchId", "");/* 交易机构(银行机构代码) */
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();
    }

    protected String[] sendToBank(String p_reqStr, String transPort) throws Exception {
        String[] tmpStrRet = new String[]{"", ""};

        // 消息报文头
        String macKey = getBankConfig().getValueAsString(tmpmacKey);
        WriteBankLogLn("通讯密钥内容1:" + macKey);
        if (StringHelper.isNullOrEmpty(macKey)) {
            tmpStrRet[0] = FailCode.E9981;
            tmpStrRet[1] = "通讯密钥内容为空,请检查配置文件config.xml中'macKey'配置信息.1";
            return tmpStrRet;
        }

        String msgMac = Mac.generateMac(macKey.getBytes(getCharset()), p_reqStr.getBytes(getCharset()));
        byte[] msgMacBytes = msgMac.getBytes(getCharset());
        if (msgMacBytes.length != 16) {
            tmpStrRet[0] = FailCode.E9981;
            tmpStrRet[1] = "生成的MAC值1:[" + msgMac + "],长度非16字节";
            return tmpStrRet;
        }

        // 消息报文
        String tmpReqMsgHeader = String.format("%08d", (msgMac + p_reqStr).getBytes(getCharset()).length) + msgMac;
        String tmpReqData = tmpReqMsgHeader + p_reqStr;
        WriteBankLogStep2(tmpReqData);

        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(transPort), this);
        WriteBankLogLn("服务地址：[" + bankFront.serverIP + ":" + transPort + "]。");

        TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpReqData.getBytes(getCharset()));
        tmpStrRet[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
            if (tmpStrRet[1].contains("<")) {
                tmpStrRet[1] = tmpStrRet[1].substring(tmpStrRet[1].indexOf('<'));
            }
        } else {
            tmpStrRet[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogStep3(tmpStrRet[1]);
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }

        return tmpStrRet;
    }

    protected String[] sendToBank(byte[] reqBytes, TcpPortClient tmpClient) throws Exception {
        String[] tmpStrRet = new String[]{"", ""};

        // 消息报文头
        String macKey = getBankConfig().getValueAsString(tmpmacKey);
        WriteBankLogLn("通讯密钥内容:" + macKey);
        if (StringHelper.isNullOrEmpty(macKey)) {
            tmpStrRet[0] =  FailCode.E9981;
            tmpStrRet[1] = "通讯密钥内容为空,请检查配置文件config.xml中'macKey'配置信息.";
            return tmpStrRet;
        }

        String msgMac = Mac.generateMac(macKey.getBytes(getCharset()), reqBytes);
        byte[] msgMacBytes = msgMac.getBytes(getCharset());
        if (msgMacBytes.length != 16) {
            tmpStrRet[0] =  FailCode.E9981;
            tmpStrRet[1] = "生成的MAC值:[" + msgMac + "]长度非16字节";
            return tmpStrRet;
        }

        // 消息报文
        WriteBankLogLn("send p_reqStr len:" + reqBytes.length);
        WriteBankLogLn("08d:" + msgMac.length() + reqBytes.length);
        String tmpReqMsgHeader = String.format("%08d", (msgMac.length() + reqBytes.length)) + msgMac;
        WriteBankLogLn("tmpReqMsgHeader:" + tmpReqMsgHeader);
        byte[] reqHeader = tmpReqMsgHeader.getBytes(getCharset());
        byte[] tmpSendBytes = new byte[reqHeader.length + reqBytes.length];
        System.arraycopy(reqHeader, 0, tmpSendBytes, 0, reqHeader.length);
        System.arraycopy(reqBytes, 0, tmpSendBytes, reqHeader.length, reqBytes.length);

        String tmpReqData = tmpReqMsgHeader + new String(reqBytes, getCharset());
        WriteBankLogStep2(tmpReqData);

        TcpReceiver tmpReceiver = tmpClient.sendMessageClose(tmpSendBytes);
        tmpStrRet[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
        } else {
            tmpStrRet[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogStep3(tmpStrRet[1]);
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }

        return tmpStrRet;
    }

    protected String[] sendToBank(String p_reqStr, TcpPortClient tmpClient) throws Exception {
        String[] tmpStrRet = new String[]{"", ""};

        // 消息报文头
        String macKey = getBankConfig().getValueAsString(tmpmacKey);
        WriteBankLogLn("通讯密钥内容:" + macKey);
        if (StringHelper.isNullOrEmpty(macKey)) {
            tmpStrRet[0] =  FailCode.E9981;
            tmpStrRet[1] = "通讯密钥内容为空,请检查配置文件config.xml中'macKey'配置信息.";
            return tmpStrRet;
        }

        String msgMac = Mac.generateMac(macKey.getBytes(getCharset()), p_reqStr.getBytes(getCharset()));
        byte[] msgMacBytes = msgMac.getBytes(getCharset());
        if (msgMacBytes.length != 16) {
            tmpStrRet[0] =  FailCode.E9981;
            tmpStrRet[1] = "生成的MAC值:[" + msgMac + "]长度非16字节";
            return tmpStrRet;
        }

        // 消息报文
        WriteBankLogLn("send p_reqStr len:" + p_reqStr.getBytes(getCharset()).length);
        WriteBankLogLn("08d:" + (msgMac + p_reqStr).getBytes(getCharset()).length);
        String tmpReqMsgHeader = String.format("%08d", (msgMac + p_reqStr).getBytes(getCharset()).length) + msgMac;
        String tmpReqData = tmpReqMsgHeader + p_reqStr;
        WriteBankLogStep2(tmpReqData);

        TcpReceiver tmpReceiver = tmpClient.sendMessageClose(tmpReqData.getBytes(getCharset()));
        tmpStrRet[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
        } else {
            tmpStrRet[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogStep3(tmpStrRet[1]);
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }

        return tmpStrRet;
    }

    protected String[] sendToBank(String tmpSbPck) throws Exception {
        String[] retStr = new String[]{"", ""};
        String serverUrl = bankFront.getUrl("pushSignData");
        WriteBankLogLn("2.提交银行的地址：" + serverUrl);
        WriteBankLogStep2(tmpSbPck);
        WebRequest tmpWebRequest = new WebRequest(serverUrl, this.bankFront, this.sbLog);
        tmpWebRequest.setConnectTimeout(getReadTimeout(120));
        //tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        tmpWebRequest.setRequestProperty("connection", "Close");
        byte[] tmpUpBytes = tmpSbPck.toString().getBytes(getCharset());
        retStr = tmpWebRequest.upload(tmpUpBytes, getCharset());
        WriteBankLogStep3(retStr[1]);
        return retStr;
    }

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1&&p_receiver.readedLength >= 24) {
                p_receiver.contentLength = Integer.parseInt(new String(p_receiver.recBytes, 0, 8, getCharset()).trim()) - 16;
                p_receiver.contentStartIndex = 24;

        }
    }
}